// Copyright (c) Microsoft Corporation. 
// Licensed under the MIT license.

#pragma once

#include "SimplygonJobData.h"
#include "LODRecipeContext.h"

struct FScopedSlowTask;
class FSimplygonProcessor;
class ULODRecipe;

/**
 * @brief LOD Recipe Manager to control building and managing LOD Recipes
*/
class LODRECIPEEDITOR_API FLODRecipeManager
{
protected:

	/**
	 * @brief constructor
	*/
	FLODRecipeManager();

public:

	/**
	 * @brief a static method to get instance of the FLODRecipeManager
	 * @return refernce to the FLODRecipeManager
	*/
	static FLODRecipeManager& Get();

	/**
	 * @brief Build all Recipes
	*/
	void BuildAll();

	/**
	 * @brief Build the following Skeletal or StaticMesh.
	*/
	void Build(TSoftObjectPtr<UObject> Mesh);

	/**
	 * @brief Build Recipes.
	 * @param LODRecipes A List of Recipes to build.
	 * @param InContext Filter context to run either static or skeletal meshes.
	*/
	void Build(const TArray<ULODRecipe*>& LODRecipes, const FLODRecipeContext& InContext = FLODRecipeContext());

private:
	using FLODRecipeMeshMap = TMap<ULODRecipe*, TArray<TSoftObjectPtr<UObject>>>;

	/**
	 * @brief Bind delegates.
	*/
	void BindDelegates();
	
	/**
	 * @brief Initalize progress.
	 * @param LODRecipes list of recipes that will run.
	 * @return total amount of work expected.
	*/
	int32 InitProgress(const FLODRecipeMeshMap& LODRecipes);
	
	/**
	 * @brief will wait untill work is completed
	 * @param TotalAmountOfWork the amount of work currently pending.
	 * @param SlowTask scoped slow task currently waiting on to complete.
	*/
	void WaitForComplete(const int32 TotalAmountOfWork, FScopedSlowTask& SlowTask);
	
	/**
	 * @brief Number of work items completed.
	*/
	volatile int32 SimplygonWorkCompleted;
	
	/**
	 * @brief Simplygon work progress.
	*/
	volatile int32 SimplygonWorkProgress;

	/**
	 * @brief delegate to track progress.
	*/
	FSimplygonProcessProgressDelegate ProgressDelegate;

	/**
	 * @brief delegate that gets called on process completion.
	*/
	FSimplygonProcessCompleteDelegate CompleteDelegate;

	/**
	 * @brief delegate that gets called on batch process completion.
	*/
	FSimplygonProcessBatchCompleteDelegate BatchCompleteDelegate;

	/**
	 * @brief delegate that called on if process failed. 
	*/
	FSimplygonProcessFailedDelegate FailedDelegate;

	/**
	 * @brief delegate that called on if batch process failed. 
	*/
	FSimplygonProcessFailedDelegate BatchFailedDelegate;

	/**
	 * @brief a process to keep track of processing job/works.
	*/
	FSimplygonProcessor* SimplygonProcessor;
	/* End ISimplygonReduction implementations*/

	/**
	 * @brief Method to filter LODRecipes
	 * @param LODRecipes list of LODRecipes
	 * @param InContext fioter criteria
	 * @param Result a map containing a LODRecipes and a UObject
	*/
	void FilterLODRecipes(const TArray<ULODRecipe*>& LODRecipes, const FLODRecipeContext& InContext, FLODRecipeMeshMap& Result);
};
